// ============================================
// 资金管理路由 - fund.js
// 包含资金管理相关的所有API路由：充值记录、资金明细等
// ============================================

// 导入必要的模块
const express = require('express'); // Express框架，用于创建Web服务器和路由
const multer = require('multer'); // 文件上传中间件，用于处理文件上传
const path = require('path'); // 路径处理模块，用于处理文件路径
const fs = require('fs'); // 文件系统模块，用于文件操作
const { body, validationResult } = require('express-validator'); // 请求参数验证中间件
const { query, get, insert } = require('../config/database'); // 数据库操作函数
const { authenticateToken } = require('../middlewares/auth'); // JWT认证中间件

// ====================
// 文件上传配置
// ====================
// 创建凭证图片目录 - 用于存储用户上传的充值凭证图片
const voucherDir = path.join(__dirname, '../uploads/vouchers');
// 检查目录是否存在，如果不存在则创建（recursive: true 表示递归创建所有父目录）
if (!fs.existsSync(voucherDir)) {
  fs.mkdirSync(voucherDir, { recursive: true });
}

// 配置multer存储 - 定义文件存储规则
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    // 指定文件存储目录
    cb(null, voucherDir);
  },
  filename: function (req, file, cb) {
    // 生成唯一文件名：时间戳 + 随机数 + 原扩展名
    // 这样可以避免文件名冲突，确保每个文件都有唯一的名称
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, 'voucher-' + uniqueSuffix + path.extname(file.originalname));
  }
});

// 文件过滤：只允许图片文件 - 增强安全性，防止上传恶意文件
const fileFilter = (req, file, cb) => {
  // 检查文件MIME类型，只允许以image/开头的文件类型（如图片）
  if (file.mimetype.startsWith('image/')) {
    cb(null, true); // 允许上传
  } else {
    cb(new Error('只允许上传图片文件'), false); // 拒绝上传并返回错误
  }
};

// 创建multer实例，配置上传参数
const upload = multer({
  storage: storage, // 使用上面定义的存储配置
  fileFilter: fileFilter, // 使用上面定义的文件过滤器
  limits: {
    fileSize: 5 * 1024 * 1024 // 限制文件大小为5MB，防止上传过大的文件
  }
});

// 创建Express路由器实例
const router = express.Router();

// ====================
// 充值相关接口（合并路由）
// ====================
// GET /recharges - 获取充值记录列表或充值信息
// 这个接口根据查询参数 _action 和 _subAction 来区分不同的操作
router.get('/recharges', authenticateToken, async (req, res) => {
  try {
    // 从查询参数中获取参数，并设置默认值
    const {
      _action,        // 操作类型：getData 表示获取数据
      _subAction,     // 子操作类型：getRechargeInfo 表示获取充值信息
      page = 1,       // 页码，默认第1页
      perPage = 10,   // 每页记录数，默认10条
      audit_status,   // 审核状态筛选条件
      created_at      // 创建日期筛选条件
    } = req.query;

    // 从JWT token中获取用户ID（在auth中间件中已经验证并添加到req.user）
    const userId = req.user.userId;

    // 根据 _action 和 _subAction 区分不同的操作
    if (_action === 'getData' && _subAction === 'getRechargeInfo') {
      // 获取充值信息（汇率、支付二维码等）- 用于充值页面显示
      const rechargeInfo = {
        alipayQrcode: '', // 模拟支付宝二维码（Base64格式）
        wxQrcode: '',    // 模拟微信二维码
        rate: '6.85', // 汇率（USD转CNY）
        bankInfo: {
          bankname: '中国银行',
          card_number: '6217********1234',
          username: '测试账户'
        }
      };

      // 返回充值信息
      res.json({
        status: 0,    // 状态码：0表示成功
        msg: '获取充值信息成功',
        data: rechargeInfo
      });
      return; // 重要：返回以避免执行后续代码
    } else {
      // 默认获取充值记录列表 - 分页查询用户的充值记录
      const offset = (page - 1) * perPage; // 计算偏移量：跳过前面多少条记录

      // 构建MySQL查询条件 - 动态构建WHERE子句
      let whereConditions = ['user_id = ?']; // 基础条件：只查询当前用户的记录
      let queryParams = [userId]; // 查询参数数组

      // 如果有审核状态筛选条件，添加到查询条件中
      if (audit_status) {
        whereConditions.push('audit_status = ?');
        queryParams.push(audit_status);
      }

      // 如果有创建日期筛选条件，添加到查询条件中
      if (created_at) {
        whereConditions.push('DATE(created_at) = ?'); // DATE()函数提取日期部分
        queryParams.push(created_at);
      }

      // 构建完整的WHERE子句，如果没有条件则为空字符串
      const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : '';

      // 获取总记录数 - 用于分页显示总页数
      const totalResult = await query(
        `SELECT COUNT(*) as total FROM recharges ${whereClause}`,
        queryParams
      );
      const total = totalResult[0].total; // 提取总数

      // 获取分页数据 - 查询当前页的记录
      const recharges = await query(
        `SELECT * FROM recharges ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
        [...queryParams, parseInt(perPage), offset] // 展开参数数组，添加LIMIT和OFFSET参数
      );

      // 返回分页数据
      res.json({
        status: 0,
        msg: '获取充值记录成功',
        data: {
          items: recharges, // 当前页的记录列表
          total: total      // 总记录数
        }
      });
    }

  } catch (error) {
    // 捕获并处理错误
    console.error('Get recharges error:', error);
    res.status(500).json({
      status: 1, // 状态码：1表示失败
      msg: '操作失败',
      data: null
    });
  }
});

// ====================
// 提交充值接口 - 完善校验与审核流程
// ====================
// POST /recharges - 提交充值申请
// 使用express-validator进行请求参数验证，确保数据完整性
router.post('/recharges', authenticateToken, [
  body('money').isFloat({ min: 1 }).withMessage('充值金额必须大于0'), // 验证金额为浮点数且大于0
  body('pay_type').isIn([1, 2, 3]).withMessage('支付类型无效，请选择1-3之间的数字'), // 验证支付类型在有效范围内
  body('voucher').notEmpty().withMessage('凭证链接不能为空') // 验证凭证链接不为空
], async (req, res) => {
  let connection; // 声明数据库连接变量，用于事务处理
  try {
    // 检查参数验证结果
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      // 如果有验证错误，返回第一个错误信息
      return res.json({
        status: 1,
        msg: errors.array()[0].msg,
        data: null
      });
    }

    // 从请求体中获取参数
    const { money, pay_type, voucher, remark } = req.body;
    const userId = req.user.userId; // 从JWT token中获取用户ID

    // 加强金额校验 - 双重验证确保金额有效性
    const moneyValue = parseFloat(money);
    if (moneyValue <= 0) {
      return res.json({
        status: 1,
        msg: '充值金额必须大于0',
        data: null
      });
    }

    // 验证支付类型是否为有效数字 - 防止前端传递无效值
    if (![1, 2, 3].includes(pay_type)) {
      return res.json({
        status: 1,
        msg: '支付类型无效，请选择1-3之间的数字',
        data: null
      });
    }

    // 检查单日充值次数限制（防止恶意充值）- 安全措施
    const today = new Date().toISOString().split('T')[0]; // 获取今天的日期（YYYY-MM-DD格式）
    const todayRecharges = await query(
      'SELECT COUNT(*) as count FROM recharges WHERE user_id = ? AND DATE(created_at) = ?',
      [userId, today] // 查询今天该用户的充值次数
    );

    // 从环境变量获取每日充值次数限制，默认10次
    const dailyLimit = process.env.DAILY_RECHARGE_LIMIT || 10;
    if (todayRecharges[0].count >= dailyLimit) {
      return res.json({
        status: 1,
        msg: `今日充值次数已达上限（${dailyLimit}次），请明天再试`,
        data: null
      });
    }

    // 检查单笔充值金额限制 - 防止过大金额充值
    const maxAmount = process.env.MAX_RECHARGE_AMOUNT || 10000;
    if (moneyValue > maxAmount) {
      return res.json({
        status: 1,
        msg: `单笔充值金额不能超过 ${maxAmount} USD`,
        data: null
      });
    }

    // 获取实时汇率（这里可以集成外部汇率API）- 计算人民币金额
    const exchangeRate = await getExchangeRate();
    const moneyCNY = moneyValue * exchangeRate; // 计算对应的人民币金额

    // 使用事务确保数据一致性 - 重要：充值记录和审核记录必须同时成功或失败
    const db = require('../config/database');
    connection = await db.beginTransaction(); // 开始事务
    
    try {
      // 插入充值记录到recharges表 - 使用事务连接执行
      const [rechargeResult] = await connection.execute(
        `INSERT INTO recharges (user_id, money, exchange_rate, money_cny, pay_type, voucher, remark, audit_status)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
        [userId, moneyValue, exchangeRate, moneyCNY, pay_type, voucher || null, remark || '', 0] // audit_status=0表示待审核
      );
      const rechargeId = rechargeResult.insertId; // 获取新插入记录的ID

      // 创建审核记录到recharge_audits表 - 记录审核状态
      await connection.execute(
        `INSERT INTO recharge_audits (recharge_id, audit_status, audit_reason, created_at)
         VALUES (?, ?, ?, NOW())`,
        [rechargeId, 0, '等待管理员审核'] // audit_status=0表示等待审核
      );

      // 提交事务 - 如果所有操作都成功，提交事务使更改永久生效
      await db.commitTransaction(connection);

      // 发送通知（可以集成邮件或消息通知系统）- 异步操作，不影响主流程
      await sendRechargeNotification(userId, rechargeId, moneyValue, pay_type);

      // 返回成功响应
      res.status(201).json({
        status: 0,
        msg: '充值申请提交成功，等待审核',
        data: {
          id: rechargeId,
          money: moneyValue,
          exchange_rate: exchangeRate,
          money_cny: moneyCNY,
          pay_type: pay_type,
          audit_status: 0,
          audit_reason: '等待管理员审核'
        }
      });

    } catch (transactionError) {
      // 回滚事务 - 如果事务中任何操作失败，回滚所有更改
      if (connection) {
        await db.rollbackTransaction(connection);
      }
      throw transactionError; // 重新抛出错误，由外层catch块处理
    }

  } catch (error) {
    // 捕获并处理所有错误
    console.error('Submit recharge error:', error);
    res.status(500).json({
      status: 1,
      msg: '提交充值失败，请稍后重试',
      data: null
    });
  }
});

// ====================
// 辅助函数：获取汇率
// ====================
// 这个函数用于获取USD到CNY的汇率
// 在实际项目中，应该调用外部汇率API获取实时汇率
async function getExchangeRate() {
  try {
    // 这里可以集成外部汇率API，暂时使用固定汇率
    // 实际项目中应该从外部API获取实时汇率，如：
    // const response = await fetch('https://api.exchangerate-api.com/v4/latest/USD');
    // const data = await response.json();
    // return data.rates.CNY;
    return 6.85; // 固定汇率，用于演示
  } catch (error) {
    // 如果获取汇率失败，使用默认汇率并记录错误
    console.error('获取汇率失败，使用默认汇率:', error);
    return 6.85; // 默认汇率
  }
}

// ====================
// 辅助函数：发送充值通知
// ====================
// 这个函数用于发送充值申请通知
// 在实际项目中，可以集成邮件、短信或系统消息通知
async function sendRechargeNotification(userId, rechargeId, amount, payType) {
  try {
    // 支付类型映射 - 将数字支付类型转换为中文描述
    const payTypeMap = {
      1: '支付宝',
      2: '微信',
      3: '银行卡'
    };
    const payTypeText = payTypeMap[payType] || payType; // 如果映射不存在，使用原始值
    
    // 这里可以集成邮件通知、短信通知或系统消息
    // 目前只是控制台输出，实际项目中应该：
    // 1. 发送邮件给管理员
    // 2. 发送系统消息给用户
    // 3. 记录到日志系统
    console.log(`充值通知：用户 ${userId} 提交了 ${amount} USD 的充值申请，支付方式：${payTypeText}`);
    
    // 实际项目中可以发送邮件给管理员
    // 或者发送系统消息给用户
  } catch (error) {
    // 通知发送失败不影响主流程，但需要记录错误
    console.error('发送充值通知失败:', error);
  }
}

// ====================
// 获取充值详情接口
// ====================
// GET /recharges/:id - 获取特定充值记录的详细信息
// 需要充值记录ID作为URL参数，并且只能查看自己的充值记录
router.get('/recharges/:id', authenticateToken, async (req, res) => {
  try {
    const { id } = req.params; // 从URL参数中获取充值记录ID
    const { _action } = req.query; // 获取操作类型参数
    const userId = req.user.userId; // 从JWT token中获取用户ID

    // 检查操作类型，确保请求的有效性
    if (_action === 'getData') {
      // 查询特定的充值记录，确保只能查看自己的记录
      const recharge = await get(
        `SELECT * FROM recharges WHERE id = ? AND user_id = ?`, // 同时验证记录ID和用户ID
        [id, userId]
      );

      // 检查记录是否存在
      if (!recharge) {
        return res.status(404).json({
          status: 1,
          msg: '充值记录不存在',
          data: null
        });
      }

      // 返回充值记录详情
      res.json({
        status: 0,
        msg: '获取充值详情成功',
        data: recharge
      });
    } else {
      // 如果操作类型无效，返回错误
      res.json({
        status: 1,
        msg: '无效的请求参数',
        data: null
      });
    }
  } catch (error) {
    // 捕获并处理数据库查询错误
    console.error('Get recharge details error:', error);
    res.status(500).json({
      status: 1,
      msg: '获取充值详情失败',
      data: null
    });
  }
});

// ====================
// 获取资金明细接口 - 完善查询条件和数据展示
// ====================
// GET /money-details - 获取用户的资金变动明细记录
// 支持多种查询条件：分页、类型筛选、日期范围、金额范围、排序等
router.get('/money-details', authenticateToken, async (req, res) => {
  try {
    // 从查询参数中获取各种筛选条件，并设置默认值
    const {
      page = 1,           // 页码，默认第1页
      perPage = 10,       // 每页记录数，默认10条
      change_type,        // 变更类型筛选（1:充值, 2:提现, 3:提现驳回, 4:开卡, 5:转入）
      start_date,         // 开始日期（YYYY-MM-DD格式）
      end_date,           // 结束日期（YYYY-MM-DD格式）
      min_amount,         // 最小金额筛选
      max_amount,         // 最大金额筛选
      sort_by = 'created_at', // 排序字段，默认按创建时间
      sort_order = 'desc'     // 排序顺序，默认降序
    } = req.query;

    const userId = req.user.userId; // 从JWT token中获取用户ID
    const offset = (page - 1) * perPage; // 计算分页偏移量

    // 构建MySQL查询条件 - 动态构建WHERE子句
    let whereConditions = ['user_id = ?']; // 基础条件：只查询当前用户的记录
    let queryParams = [userId]; // 查询参数数组

    // 根据各种筛选条件动态添加查询条件
    if (change_type) {
      whereConditions.push('change_type = ?');
      queryParams.push(change_type);
    }

    if (start_date) {
      whereConditions.push('DATE(created_at) >= ?'); // 使用DATE()函数比较日期部分
      queryParams.push(start_date);
    }

    if (end_date) {
      whereConditions.push('DATE(created_at) <= ?');
      queryParams.push(end_date);
    }

    if (min_amount) {
      whereConditions.push('amount >= ?');
      queryParams.push(parseFloat(min_amount));
    }

    if (max_amount) {
      whereConditions.push('amount <= ?');
      queryParams.push(parseFloat(max_amount));
    }

    // 构建完整的WHERE子句
    const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : '';

    // 验证排序字段和顺序，防止SQL注入
    const validSortFields = ['created_at', 'amount', 'change_type']; // 允许的排序字段
    const validSortOrders = ['asc', 'desc']; // 允许的排序顺序
    
    // 检查排序字段是否有效，无效则使用默认值
    const sortField = validSortFields.includes(sort_by) ? sort_by : 'created_at';
    // 检查排序顺序是否有效，无效则使用默认值
    const sortOrder = validSortOrders.includes(sort_order.toLowerCase()) ? sort_order.toUpperCase() : 'DESC';

    // 获取总记录数 - 用于分页显示总页数
    const totalResult = await query(
      `SELECT COUNT(*) as total FROM money_details ${whereClause}`,
      queryParams
    );
    const total = totalResult[0].total;

    // 获取分页数据 - 查询当前页的记录
    const moneyDetails = await query(
      `SELECT
         id,
         change_type,
         amount,
         balance,
         description,
         related_id,
         related_type,
         DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as created_at  -- 格式化日期时间显示
       FROM money_details
       ${whereClause}
       ORDER BY ${sortField} ${sortOrder}  -- 动态排序
       LIMIT ? OFFSET ?  -- 分页限制`,
      [...queryParams, parseInt(perPage), offset]
    );

    // 格式化响应数据 - 为前端展示准备数据
    const formattedDetails = moneyDetails.map(detail => {
      // 根据change_type判断金额正负号
      let changeMoney = parseFloat(detail.amount);
      let changeMoneyFormatted = formatCurrency(Math.abs(changeMoney));
      
      // 根据变更类型确定金额符号（使用新的数字映射）
      // 1:充值, 2:提现, 3:提现驳回, 4:开卡, 5:转入
      // 只有1:充值和3:提现驳回为+号（增加资金），其他三项都是消费类型为-号（减少资金）
      if (detail.change_type === 1 || detail.change_type === 3) {
        changeMoneyFormatted = '+' + changeMoneyFormatted; // 正数，资金增加
      } else {
        changeMoneyFormatted = '-' + changeMoneyFormatted; // 负数，资金减少
      }
      
      // 计算变动前的金额：当前余额减去变动金额
      const beforeMoney = parseFloat(detail.balance) - changeMoney;
      
      // 返回格式化后的记录，添加前端需要的字段
      return {
        ...detail, // 保留原始字段
        // 添加前端所需的字段
        before_money: formatCurrency(beforeMoney),        // 变动前金额
        change_money: changeMoneyFormatted,               // 变动金额（带正负号）
        after_money: formatCurrency(detail.balance),      // 变动后金额（当前余额）
        // 添加类型中文描述
        change_type_text: getChangeTypeText(detail.change_type), // 类型中文名称
        // 格式化金额显示
        amount_formatted: formatCurrency(detail.amount),  // 格式化金额
        balance_formatted: formatCurrency(detail.balance), // 格式化余额
        // 添加图标类型（用于前端显示不同图标）
        icon_type: getIconType(detail.change_type)
      };
    });

    // 获取统计信息 - 按变更类型分组统计
    const statsResult = await query(
      `SELECT
         change_type,
         COUNT(*) as count,
         SUM(amount) as total_amount
       FROM money_details
       WHERE user_id = ?
       GROUP BY change_type`,
      [userId]
    );

    // 构建统计信息对象
    const statistics = {
      total_count: total, // 总记录数
      type_stats: statsResult.reduce((acc, stat) => {
        // 将统计结果转换为对象格式，以变更类型为键
        acc[stat.change_type] = {
          count: stat.count,
          total_amount: parseFloat(stat.total_amount || 0) // 确保金额为数字类型
        };
        return acc;
      }, {})
    };

    // 返回分页数据和统计信息
    res.json({
      status: 0,
      msg: '获取资金明细成功',
      data: {
        items: formattedDetails, // 格式化后的记录列表
        total: total             // 总记录数
      }
    });

  } catch (error) {
    // 捕获并处理数据库查询错误
    console.error('Get money details error:', error);
    res.status(500).json({
      status: 1,
      msg: '获取资金明细失败',
      data: null
    });
  }
});

// ====================
// 辅助函数：获取变更类型中文描述
// ====================
// 这个函数将数字类型的变更类型转换为中文描述
// 用于前端显示友好的类型名称
function getChangeTypeText(changeType) {
  const typeMap = {
    1: '充值',      // 用户充值
    2: '提现',      // 用户提现
    3: '提现驳回',  // 提现申请被驳回
    4: '开卡',      // 开通卡片
    5: '转入'       // 资金转入
  };
  return typeMap[changeType] || changeType; // 如果映射不存在，返回原始值
}

// ====================
// 辅助函数：格式化货币金额
// ====================
// 这个函数将金额格式化为两位小数
// 用于统一金额显示格式
function formatCurrency(amount) {
  return parseFloat(amount).toFixed(2); // 转换为浮点数并保留两位小数
}

// ====================
// 辅助函数：获取图标类型
// ====================
// 这个函数根据变更类型返回对应的图标类型
// 用于前端显示不同的图标样式
function getIconType(changeType) {
  const iconMap = {
    1: 'success',   // 充值 - 成功图标（绿色）
    2: 'warning',   // 提现 - 警告图标（黄色）
    3: 'info',      // 提现驳回 - 信息图标（蓝色）
    4: 'primary',   // 开卡 - 主要图标（蓝色）
    5: 'primary'    // 转入 - 主要图标（蓝色）
  };
  return iconMap[changeType] || 'default'; // 默认图标类型
}

// ====================
// 辅助函数：获取可用的变更类型
// ====================
// 这个函数返回所有可用的变更类型配置
// 用于前端筛选下拉框等场景
function getAvailableChangeTypes() {
  return [
    { value: 1, label: '充值', color: '#67C23A' },      // 绿色
    { value: 2, label: '提现', color: '#E6A23C' },      // 黄色
    { value: 3, label: '提现驳回', color: '#409EFF' },  // 蓝色
    { value: 4, label: '开卡', color: '#F56C6C' },      // 红色
    { value: 5, label: '转入', color: '#909399' }       // 灰色
  ];
}

// ====================
// 充值凭证上传接口
// ====================
// POST /custom_upload_rich - 上传充值凭证图片
// 使用multer中间件处理文件上传，只允许图片文件，最大5MB
router.post('/custom_upload_rich', authenticateToken, upload.single('file'), async (req, res) => {
  try {
    // 检查是否成功接收到文件
    if (!req.file) {
      return res.json({
        status: 1,
        msg: '请选择要上传的凭证图片',
        data: null
      });
    }

    const userId = req.user.userId; // 从JWT token中获取用户ID
    
    // 生成文件访问URL（相对路径）- 用于数据库存储
    const fileUrl = `/uploads/vouchers/${req.file.filename}`;
    
    // 生成完整可查看图片的URL - 用于前端直接访问
    const fullImageUrl = `${req.protocol}://${req.get('host')}${fileUrl}`;
    
    // 返回上传成功信息 - 按照前端voucherSuccess函数要求添加url字段
    res.json({
      status: 0,
      msg: '凭证上传成功',
      url: fullImageUrl,  // 与status同级的url字段，返回完整可查看图片的链接（前端直接使用）
      data: {
        url: fileUrl,           // 相对路径，用于数据库存储
        filename: req.file.filename,      // 服务器上的文件名
        originalname: req.file.originalname, // 原始文件名
        size: req.file.size,              // 文件大小（字节）
        mimetype: req.file.mimetype       // 文件MIME类型
      }
    });

  } catch (error) {
    // 捕获并处理文件上传错误
    console.error('Upload voucher error:', error);
    
    // 处理multer特定的错误
    if (error instanceof multer.MulterError) {
      if (error.code === 'LIMIT_FILE_SIZE') {
        // 文件大小超过限制的错误
        return res.json({
          status: 1,
          msg: '文件大小不能超过5MB',
          data: null
        });
      }
      // 可以在这里添加其他multer错误处理
    }
    
    // 处理其他未知错误
    res.status(500).json({
      status: 1,
      msg: '凭证上传失败',
      data: null
    });
  }
});

// 导出路由器，以便在app.js中注册路由
module.exports = router;